package net.oschina.git.utils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.LsRemoteCommand;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig;
import org.eclipse.jgit.transport.SshTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;

import com.jcraft.jsch.Session;

public class GitUtil {
	public static void cloneByPassword(String dir, String Url, String username, String password,
			IProgressMonitor progressMonitor)
			throws IllegalStateException, GitAPIException, InvocationTargetException, InterruptedException {
		File localDir = new File(dir);
		CloneCommand cloneCommand = Git.cloneRepository();
		GitProgressMonitor gProMon = new GitProgressMonitor(progressMonitor);
		cloneCommand.setProgressMonitor(gProMon);
		cloneCommand.setURI(Url).setDirectory(localDir);
		cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
		cloneCommand.call();
	}

	public static String testRepByPassword(String url, String username, String password)
			throws InvalidRemoteException, TransportException, GitAPIException {
		final LsRemoteCommand lsCmd = new LsRemoteCommand(null);
		lsCmd.setRemote(url);
		lsCmd.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
		return lsCmd.call().toString();
	}

	public static String testRepBySSH(String url) throws InvalidRemoteException, TransportException, GitAPIException {
		final LsRemoteCommand lsCmd = new LsRemoteCommand(null);
		lsCmd.setRemote(url);
		return lsCmd.call().toString();
	}

	public static Repository getRepository(String path) throws IOException {
		Git git = Git.open(new File(path + "/.git"));
		return git.getRepository();
	}

	public static void createRepository(String path, String remotePath)
			throws IllegalStateException, GitAPIException, IOException {
		Git git = Git.init().setDirectory(new File(path)).call();
		git.add().addFilepattern(".").call();
		git.commit().setMessage("first commit").call();
		PushCommand pushCommand = git.push();
		pushCommand.setTransportConfigCallback(new TransportConfigCallback() {
			@Override
			public void configure(Transport transport) {
				SshTransport sshTransport = (SshTransport) transport;
				sshTransport.setSshSessionFactory(new JschConfigSessionFactory() {
					@Override
					protected void configure(OpenSshConfig.Host host, Session session) {
					}
				});
			}
		});
		pushCommand.setRemote(remotePath).call();
		StoredConfig config = git.getRepository().getConfig();
		config.setString("remote", "origin", "url", path);
		config.save();
	}

	public static void createRepository(String path, String remotePath, String username, String password)
			throws IllegalStateException, GitAPIException, IOException {
		Git git = Git.init().setDirectory(new File(path)).call();
		git.add().addFilepattern(".").call();
		git.commit().setMessage("first commit").call();
		git.push().setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password))
				.setRemote(remotePath).call();
		StoredConfig config = git.getRepository().getConfig();
		config.setString("remote", "origin", "url", path);
		config.save();
	}

	public static void cloneBySSH(String dir, String Url, IProgressMonitor progressMonitor)
			throws InvalidRemoteException, TransportException, GitAPIException {
		File localDir = new File(dir);
		CloneCommand cloneCommand = Git.cloneRepository();
		cloneCommand.setProgressMonitor(new GitProgressMonitor(progressMonitor));
		cloneCommand.setURI(Url).setDirectory(localDir);
		CredentialsProvider allowHosts = new CredentialsProvider() {

			@Override
			public boolean supports(CredentialItem... items) {
				for (CredentialItem item : items) {
					if ((item instanceof CredentialItem.YesNoType)) {
						return true;
					}
				}
				return false;
			}

			@Override
			public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
				for (CredentialItem item : items) {
					if (item instanceof CredentialItem.YesNoType) {
						((CredentialItem.YesNoType) item).setValue(true);
						return true;
					}
				}
				return false;
			}

			@Override
			public boolean isInteractive() {
				return false;
			}
		};
		cloneCommand.setCredentialsProvider(allowHosts);
		cloneCommand.call();
	}
}
